--[[
    @Author       : baidwwy
    @Date         : 2021-02-11 11:49:09
    @LastEditTime : 2021-03-09 04:05:40
--]]

local _ENV = require("GGE界面")

local function _刷新(self)
    local y = self._py
    for i,v in ipairs(self.子控件) do
        v._i = i
        --列表之外不可见,以减少draw call
        v.是否可见 = y+v.py+v.高度>0--列表上面
        if v.是否可见 and y+v.py>self.高度 then--列表下面
            v.是否可见 = false
        end
        v:置坐标(v.px,y+v.py)
        y = y + v.高度+self.行间距
    end

    if y-self._py>self.高度 then--可以滚动的最大值
        self._max = y-self._py-self.高度
    else
        self._max = 0
    end
    
    self:置选中(self.选中行)

    local _,x,y = 窗口:取鼠标状态()
    local i,item = self:检查项目(x,y)
    if item then
        if self.焦点精灵 then
            self.焦点精灵:置中心(-item.x,-item.y)
            self.焦点精灵:置区域(0,0,item.宽度,item.高度)
        end
        self.焦点行 = i
    end
end

GUI列表 = class("GUI列表",GUI控件)
GUI列表._type  = 10
function GUI列表:初始化()
    
    self._py    = 0 --滚动值
    self._max   = 0 --滚动最大值

    self.行间距 = 0
    self.选中行 = 0
    self.焦点行 = 0

    self.文字  = require("SDL.文字")("simsun.ttc",14,true)
    self.行高度  = self.文字:取高度("A")+1

    self.选中精灵 = require("SDL.精灵")(0,0,0,self.宽度,0):置颜色(0,255,0,128)
    self.焦点精灵 = require("SDL.精灵")(0,0,0,self.宽度,0):置颜色(255,255,0,128)
end

function GUI列表:_更新(dt)
    GUI控件._更新(self,dt)
end

function GUI列表:_显示(...)
    local _x,_y = self:取坐标()
    窗口:置区域(_x,_y,self.宽度,self.高度)
        if self.选中精灵 then self.选中精灵:显示(_x,_y) end
        if self.焦点精灵 then self.焦点精灵:显示(_x,_y) end
    窗口:置区域()
    GUI控件._显示(self,...)
end

function GUI列表:清空()
    self.子控件 = {}
    self.选中行 = 0
    self.焦点行 = 0
end

function GUI列表:添加(...)
    return self:插入(#self.子控件+1,...)
end

function GUI列表:插入(i,文本,x,y,w,h)
    local r = GUI控件(文本,0,0,w or self.宽度,(h or self.行高度),self)
    r.px = x or 0;r.py = y or 0
    r.相对坐标 = false
    r.精灵 = self.文字:取精灵(文本)
    
    if type(self.子显示)=='function' then
        r.显示 = function (this,x,y)
            self:子显示(x,y,this._i)
        end
    end
    table.insert(self.子控件, i,r)
    _刷新(self)
    return r
end

function GUI列表:删除(i)
    if self.子控件[i] then
        table.remove(self.子控件,i)
        _刷新(self)
    end
end

function GUI列表:取项目(i)
    return self.子控件[i]
end

function GUI列表:置文字(v)
    self.文字 = v
    self.行高度 = self.文字:取高度("A")
    return self
end

function GUI列表:置颜色(i,...)
    if self.子控件[i] and self.子控件[i].精灵 then
        self.子控件[i].精灵:置颜色(...)
    end
    return self
end

function GUI列表:置文本(i,v)
    if self.子控件[i] then
        self.子控件[i].名称 = v
        self.子控件[i].精灵 = v and self.文字:取精灵(v)
    end
    return self
end

function GUI列表:取文本(i)
    return self.子控件[i] and self.子控件[i].名称
end

function GUI列表:取行数()
    return #self.子控件
end

function GUI列表:置选中(i)
    if self.子控件[i] then
        self.选中行 = i
        local item = self.子控件[i]
        if self.选中精灵 then
            self.选中精灵:置中心(-item.x,-item.y)
            self.选中精灵:置区域(0,0,item.宽度,item.高度)
        end
    else
        self.选中行 = 0
        if self.选中精灵 then self.选中精灵:置区域(0,0,0,0) end
    end
end

function GUI列表:取选中()
    if self.选中行 then
        return self.子控件[self.选中行]
    end
end

function GUI列表:检查项目(x,y)
    for i,item in ipairs(self.子控件) do
        if item.是否可见 and item:检查点(x,y) then
            return i,item
        end
    end
end

function GUI列表:绑定滑块(obj)
    self.滑块 = obj
    if obj then
        obj._置位置 = obj._置位置 or obj.置位置
        obj.置位置 = function (this,v)
            this._置位置(this,v)
            self._py = -math.floor(this.位置/this.最大值*self._max)
            _刷新(self)
        end
    end
    return obj
end

function GUI列表:_消息事件(msg)
    GUI控件._消息事件(self,msg)
    if not self.是否禁止 then
        for _,v in ipairs(msg.鼠标) do
            if v.type==SDL.鼠标_按下 then
                if self:检查点(v.x,v.y) then
                    v.type = nil
                    local i,item = self:检查项目(v.x,v.y)
                    if item then
                        self.选中行 = i
                        local x,y = item:取坐标()
                        self:发送消息("左键按下",x,y,i,item,msg)
                    end
                end
            elseif v.type==SDL.鼠标_弹起 then
                if self:检查点(v.x,v.y) then
                    v.type = nil
                    local i,item = self:检查项目(v.x,v.y)
                    if item and self.选中行 == i then
                        local x,y = item:取坐标()
                        if self:取类型()=='树形列表' then
                            item.是否展开 = not item.是否展开
                            self:刷新()
                            item:发送消息("左键弹起",x,y,i,item,msg)  
                        end
                        if self.选中精灵 then
                            self.选中精灵:置中心(-item.x,-item.y)
                            self.选中精灵:置区域(0,0,item.宽度,item.高度)
                        end
                        self:发送消息("左键弹起",x,y,i,item,msg)  
                    end
                end
            elseif v.type==SDL.鼠标_移动 then
                if self:检查点(v.x,v.y) then
                    v.type = nil
                    local i,item = self:检查项目(v.x,v.y)
                    if item then
                        if self.焦点精灵 then
                            self.焦点精灵:置中心(-item.x,-item.y)
                            self.焦点精灵:置区域(0,0,item.宽度,item.高度)
                        end
                        self.焦点行 = i
                        local x,y = item:取坐标()
                        self:发送消息("获得鼠标",x,y,i,item,msg)  
                    end
                end
            elseif v.type==SDL.鼠标_滚轮 then
                local _,x,y = 窗口:取鼠标状态()
                if self:检查点(x,y) then
                    v.type = nil
                    self._py = self._py+v.y*10

                    if self._py>0 then
                        self._py=0
                    end
                    if math.abs(self._py)>self._max then
                        self._py = -self._max
                    end
                    _刷新(self)

                    if self.滑块 and math.abs(self._py)>self._max then
                        self.滑块:_置位置(math.floor(math.abs(self._py)/self._max*self.滑块.最大值))
                    end
                end
            end
        end
    end
end


local function _刷新树(root,node)
    for _,v in ipairs(node) do
        table.insert(root.子控件,v)
        if v.是否展开 then--递归子项
            _刷新树(root,v._node)
        end
    end
end

local 节点 = class("节点",GUI控件)

function 节点:初始化(t,x,y,w,h,f)
    self.是否展开 = true
    self._node    = {}
    self._lay     = 1

    self.px       = x or 0
    self.py       = y or 0
    self.相对坐标 = false
    self.精灵     = f.文字:取精灵(t)
end

function 节点:添加(t,x,y)
    local r = 节点(t,self._lay*self.父控件.缩进宽度+(x or 0),y,w or self.宽度,(h or self.父控件.行高度),self.父控件)
    r.父节点 = self
    r._lay = self._lay+1

    table.insert(self._node, r)
    return r
end


GUI树形列表 = class("GUI树形列表",GUI列表)
GUI树形列表._type = 12
function GUI树形列表:初始化()
    
    self._node = {}
    self.缩进宽度 = 15
end

function GUI树形列表:添加(t,x,y)
    local r = 节点(t,x,y,w or self.宽度,(h or self.行高度),self)

    table.insert(self._node, r)
    return r
end

function GUI树形列表:刷新()
    GUI列表.清空(self)
    _刷新树(self,self._node)
    _刷新(self)
end

function GUI树形列表:清空()
    self._node = {}
    GUI列表.清空(self)
end



GUI多列列表 = class("GUI多列列表",GUI列表)
GUI多列列表._type = 11
function GUI多列列表:初始化()
    
    self._info = {}
end

function GUI多列列表:添加列(x,y,w,h)
    local t = {x=x,y=y,w=w,h=h}
    table.insert(self._info, t)
    return t
end

function GUI多列列表:添加(...)
    local r = GUI列表.添加(self)
    self[#self+1] = r
    for i,v in ipairs(self._info) do
        local r = r:创建控件(i,v.x,v.y,v.w or 50,v.h or r.高度)
        r.文本 = select(i, ...)
        r.精灵 = self.文字:取精灵(r.文本)
    end
    return r
end
